home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevpdfp.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  11.9 KB  |  399 lines

  1. /* Copyright (C) 1996, 2000 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevpdfp.c,v 1.10.2.2 2000/11/09 23:19:36 rayjj Exp $ */
  20. /* Get/put parameters for PDF-writing driver */
  21. #include "memory_.h"        /* should be first */
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gdevpdfx.h"
  25. #include "gsparamx.h"
  26.  
  27. /*
  28.  * The pdfwrite device supports the following "real" parameters:
  29.  *      OutputFile <string>
  30.  *      all the Distiller parameters (also see gdevpsdp.c)
  31.  * Only some of the Distiller parameters actually have any effect.
  32.  *
  33.  * The device also supports the following write-only pseudo-parameters that
  34.  * serve only to communicate other information from the PostScript file.
  35.  * Their "value" is an array of strings, some of which may be the result
  36.  * of converting arbitrary PostScript objects to string form.
  37.  *      pdfmark - see gdevpdfm.c
  38.  *    DSC - processed in this file
  39.  */
  40. private int pdf_dsc_process(P2(gx_device_pdf * pdev,
  41.                    const gs_param_string_array * pma));
  42.  
  43. private const int CoreDistVersion = 4000;    /* Distiller 4.0 */
  44. private const gs_param_item_t pdf_param_items[] = {
  45. #define pi(key, type, memb) { key, type, offset_of(gx_device_pdf, memb) }
  46.  
  47.     /* Acrobat Distiller 4 parameters */
  48.  
  49.     /*
  50.      * EndPage and StartPage are renamed because EndPage collides with
  51.      * a page device parameter.
  52.      */
  53.     pi("PDFEndPage", gs_param_type_int, EndPage),
  54.     pi("PDFStartPage", gs_param_type_int, StartPage),
  55.     pi("Optimize", gs_param_type_bool, Optimize),
  56.     pi("ParseDSCCommentsForDocInfo", gs_param_type_bool,
  57.        ParseDSCCommentsForDocInfo),
  58.     pi("ParseDSCComments", gs_param_type_bool, ParseDSCComments),
  59.     pi("EmitDSCWarnings", gs_param_type_bool, EmitDSCWarnings),
  60.     pi("CreateJobTicket", gs_param_type_bool, CreateJobTicket),
  61.     pi("PreserveEPSInfo", gs_param_type_bool, PreserveEPSInfo),
  62.     pi("AutoPositionEPSFiles", gs_param_type_bool, AutoPositionEPSFiles),
  63.     pi("PreserveCopyPage", gs_param_type_bool, PreserveCopyPage),
  64.     pi("UsePrologue", gs_param_type_bool, UsePrologue),
  65.  
  66.     /* Ghostscript-specific parameters */
  67.  
  68.     pi("ReAssignCharacters", gs_param_type_bool, ReAssignCharacters),
  69.     pi("ReEncodeCharacters", gs_param_type_bool, ReEncodeCharacters),
  70.     pi("FirstObjectNumber", gs_param_type_long, FirstObjectNumber),
  71. #undef pi
  72.     gs_param_item_end
  73. };
  74.   
  75. /*
  76.   Notes on implementing the remaining Distiller functionality
  77.   ===========================================================
  78.  
  79.   Architectural issues
  80.   --------------------
  81.  
  82.   Must disable all color conversions, so that driver gets original color
  83.     and color space -- needs "protean" device color space
  84.   Must optionally disable application of TR, BG, UCR similarly.  Affects:
  85.     PreserveHalftoneInfo
  86.     PreserveOverprintSettings
  87.     TransferFunctionInfo
  88.     UCRandBGInfo
  89.  
  90.   * = requires architectural change to complete
  91.  
  92.   Current limitations
  93.   -------------------
  94.  
  95.   Non-primary elements in HalftoneType 5 are not written correctly
  96.   Doesn't recognize Default TR/HT/BG/UCR
  97.   Optimization is a separate program
  98.  
  99.   Optimizations
  100.   -------------
  101.  
  102.   Create shared resources for Indexed (and other) color spaces
  103.   Remember image XObject IDs for sharing
  104.   Remember image and pattern MD5 fingerprints for sharing -- see
  105.     CD-ROM from dhoff@margnat.com
  106.   Merge font subsets?  (k/ricktest.ps, from rick@dgii.com re file output
  107.     size ps2pdf vs. pstoedit)
  108.   Minimize tables for embedded TT fonts (requires renumbering glyphs)
  109.   Clip off image data outside bbox of clip path?
  110.  
  111.   Acrobat Distiller 3
  112.   -------------------
  113.  
  114.   ---- Other functionality ----
  115.  
  116.   Embed CID fonts
  117.   Compress TT, CFF, CID/TT, and CID/CFF if CompressPages
  118.   Compress forms, Type 3 fonts, and Cos streams
  119.  
  120.   ---- Image parameters ----
  121.  
  122.   AntiAlias{Color,Gray,Mono}Images
  123.   AutoFilter{Color,Gray}Images
  124.     Needs to scan image
  125.   Convert CIE images to Device if can't represent color space
  126.  
  127.   ---- Other parameters ----
  128.  
  129.   CompressPages
  130.     Compress things other than page contents
  131.   * PreserveHalftoneInfo
  132.   PreserveOPIComments
  133.     ? see OPI spec?
  134.   * PreserveOverprintSettings
  135.   * TransferFunctionInfo
  136.   * UCRandBGInfo
  137.   ColorConversionStrategy
  138.     Select color space for drawing commands
  139.   ConvertImagesToIndexed
  140.     Postprocess image data *after* downsampling (requires an extra pass)
  141.  
  142.   Acrobat Distiller 4
  143.   -------------------
  144.  
  145.   ---- Other functionality ----
  146.  
  147.   Document structure pdfmarks
  148.  
  149.   ---- Parameters ----
  150.  
  151.   xxxDownsampleType = /Bicubic
  152.     Add new filter (or use siscale?) & to setup (gdevpsdi.c)
  153.   Binding
  154.     ? not sure where this goes (check with AD4)
  155.   DetectBlends
  156.     Idiom recognition?  PatternType 2 patterns / shfill?  (see AD4)
  157.   DoThumbnails
  158.     Also output to memory device -- resolution issue
  159.   EndPage / StartPage
  160.     Only affects AR? -- see what AD4 produces
  161.   ###Profile
  162.     Output in ICCBased color spaces
  163.   ColorConversionStrategy
  164.   * Requires suppressing CIE => Device color conversion
  165.     Convert other CIE spaces to ICCBased
  166.   CannotEmbedFontPolicy
  167.     Check when trying to embed font -- how to produce warning?
  168.  
  169.   ---- Job-level control ----
  170.  
  171.   ParseDSCComments
  172.   ParseDSCCommentsForDocInfo
  173.   EmitDSCWarnings
  174.     Require DSC parser / interceptor
  175.   CreateJobTicket
  176.     ?
  177.   PreserveEPSInfo
  178.   AutoPositionEPSFiles
  179.     Require DSC parsing
  180.   PreserveCopyPage
  181.     Concatenate Contents streams
  182.   UsePrologue
  183.     Needs hack in top-level control?
  184.  
  185. */
  186.  
  187. /* ---------------- Get parameters ---------------- */
  188.  
  189. /* Get parameters. */
  190. int
  191. gdev_pdf_get_params(gx_device * dev, gs_param_list * plist)
  192. {
  193.     gx_device_pdf *pdev = (gx_device_pdf *) dev;
  194.     float cl = (float)pdev->CompatibilityLevel;
  195.     int code = gdev_psdf_get_params(dev, plist);
  196.     int cdv = CoreDistVersion;
  197.  
  198.     if (code < 0 ||
  199.     (code = param_write_int(plist, "CoreDistVersion", &cdv)) < 0 ||
  200.     (code = param_write_float(plist, "CompatibilityLevel", &cl)) < 0 ||
  201.     /* Indicate that we can process pdfmark and DSC. */
  202.     (param_requested(plist, "pdfmark") > 0 &&
  203.      (code = param_write_null(plist, "pdfmark")) < 0) ||
  204.     (param_requested(plist, "DSC") > 0 &&
  205.      (code = param_write_null(plist, "DSC")) < 0) ||
  206.     (code = gs_param_write_items(plist, pdev, NULL, pdf_param_items)) < 0
  207.     );
  208.     return code;
  209. }
  210.  
  211. /* ---------------- Put parameters ---------------- */
  212.  
  213. /* Put parameters. */
  214. int
  215. gdev_pdf_put_params(gx_device * dev, gs_param_list * plist)
  216. {
  217.     gx_device_pdf *pdev = (gx_device_pdf *) dev;
  218.     int ecode, code;
  219.     gx_device_pdf save_dev;
  220.     float cl = (float)pdev->CompatibilityLevel;
  221.     bool locked = pdev->params.LockDistillerParams;
  222.     gs_param_name param_name;
  223.  
  224.     /*
  225.      * If this is a pseudo-parameter (pdfmark or DSC),
  226.      * don't bother checking for any real ones.
  227.      */
  228.  
  229.     {
  230.     gs_param_string_array ppa;
  231.  
  232.     code = param_read_string_array(plist, (param_name = "pdfmark"), &ppa);
  233.     switch (code) {
  234.         case 0:
  235.         pdf_open_document(pdev);
  236.         code = pdfmark_process(pdev, &ppa);
  237.         if (code >= 0)
  238.             return code;
  239.         /* falls through for errors */
  240.         default:
  241.         param_signal_error(plist, param_name, code);
  242.         return code;
  243.         case 1:
  244.         break;
  245.     }
  246.  
  247.     code = param_read_string_array(plist, (param_name = "DSC"), &ppa);
  248.     switch (code) {
  249.         case 0:
  250.         pdf_open_document(pdev);
  251.         code = pdf_dsc_process(pdev, &ppa);
  252.         if (code >= 0)
  253.             return code;
  254.         /* falls through for errors */
  255.         default:
  256.         param_signal_error(plist, param_name, code);
  257.         return code;
  258.         case 1:
  259.         break;
  260.     }
  261.     }
  262.   
  263.     /* Check for LockDistillerParams before doing anything else. */
  264.  
  265.     ecode = code = param_read_bool(plist, "LockDistillerParams", &locked);
  266.     if (locked && pdev->params.LockDistillerParams)
  267.     return ecode;
  268.  
  269.     /* General parameters. */
  270.  
  271.     {
  272.     int cdv = CoreDistVersion;
  273.  
  274.     ecode = param_put_int(plist, (param_name = "CoreDistVersion"), &cdv, ecode);
  275.     if (cdv != CoreDistVersion)
  276.         param_signal_error(plist, param_name, ecode = gs_error_rangecheck);
  277.     }
  278.  
  279.     save_dev = *pdev;
  280.  
  281.     switch (code = param_read_float(plist, (param_name = "CompatibilityLevel"), &cl)) {
  282.     default:
  283.         ecode = code;
  284.         param_signal_error(plist, param_name, ecode);
  285.     case 0:
  286.     case 1:
  287.         break;
  288.     }
  289.  
  290.     code = gs_param_read_items(plist, pdev, pdf_param_items);
  291.     if (code < 0)
  292.     ecode = code;
  293.     {
  294.     /*
  295.      * Setting FirstObjectNumber is only legal if the file
  296.      * has just been opened and nothing has been written,
  297.      * or if we are setting it to the same value.
  298.      */
  299.     long fon = pdev->FirstObjectNumber;
  300.  
  301.     if (fon != save_dev.FirstObjectNumber) {
  302.         if (fon <= 0 || fon > 0x7fff0000 ||
  303.         (pdev->next_id != 0 &&
  304.          pdev->next_id !=
  305.          save_dev.FirstObjectNumber + pdf_num_initial_ids)
  306.         ) {
  307.         ecode = gs_error_rangecheck;
  308.         param_signal_error(plist, "FirstObjectNumber", ecode);
  309.         }
  310.     }
  311.     }
  312.     {
  313.     /*
  314.      * Set ProcessColorModel now, because gx_default_put_params checks
  315.      * it.
  316.      */
  317.     static const char *const pcm_names[] = {
  318.         "DeviceGray", "DeviceRGB", "DeviceCMYK", 0
  319.     };
  320.     static const gx_device_color_info pcm_color_info[] = {
  321.         dci_values(1, 8, 255, 0, 256, 0),
  322.         dci_values(3, 24, 255, 255, 256, 256),
  323.         dci_values(4, 32, 255, 255, 256, 256)
  324.     };
  325.     int pcm = -1;
  326.  
  327.     ecode = param_put_enum(plist, "ProcessColorModel", &pcm,
  328.                    pcm_names, ecode);
  329.     if (pcm >= 0) {
  330.         pdev->color_info = pcm_color_info[pcm];
  331.         pdf_set_process_color_model(pdev);
  332.     }
  333.     }
  334.     if (ecode < 0)
  335.     goto fail;
  336.     /*
  337.      * We have to set version to the new value, because the set of
  338.      * legal parameter values for psdf_put_params varies according to
  339.      * the version.
  340.      */
  341.     pdev->version = (cl < 1.2 ? psdf_version_level2 : psdf_version_ll3);
  342.     ecode = gdev_psdf_put_params(dev, plist);
  343.     if (ecode < 0)
  344.     goto fail;
  345.     /*
  346.      * Acrobat Reader 4.0 and earlier don't handle user-space coordinates
  347.      * larger than 32K.  To compensate for this, reduce the resolution so that
  348.      * the page size in device space (which we equate to user space) is
  349.      * significantly less than 32K.  Note that this still does not protect
  350.      * us against input files that use coordinates far outside the page
  351.      * boundaries.
  352.      */
  353. #define MAX_EXTENT 28000
  354.     /* Changing resolution or page size requires closing the device, */
  355.     if (dev->height > MAX_EXTENT || dev->width > MAX_EXTENT) {
  356.     double factor =
  357.         max(dev->height / (double)MAX_EXTENT,
  358.         dev->width / (double)MAX_EXTENT);
  359.  
  360.     if (dev->is_open)
  361.         gs_closedevice(dev);
  362.     gx_device_set_resolution(dev, dev->HWResolution[0] / factor,
  363.                  dev->HWResolution[1] / factor);
  364.     }
  365. #undef MAX_EXTENT
  366.     if (pdev->FirstObjectNumber != save_dev.FirstObjectNumber) {
  367.     if (pdev->xref.file != 0) {
  368.         fseek(pdev->xref.file, 0L, SEEK_SET);
  369.         pdf_initialize_ids(pdev);
  370.     }
  371.     }
  372.     /* Handle the float/double mismatch. */
  373.     pdev->CompatibilityLevel = (int)(cl * 10 + 0.5) / 10.0;
  374.     return 0;
  375.  fail:
  376.     /* Restore all the parameters to their original state. */
  377.     pdev->version = save_dev.version;
  378.     pdev->color_info = save_dev.color_info;
  379.     pdf_set_process_color_model(pdev);
  380.     {
  381.     const gs_param_item_t *ppi = pdf_param_items;
  382.  
  383.     for (; ppi->key; ++ppi)
  384.         memcpy((char *)pdev + ppi->offset,
  385.            (char *)&save_dev + ppi->offset,
  386.            gs_param_type_sizes[ppi->type]);
  387.     }
  388.     return ecode;
  389. }
  390.  
  391. /* ---------------- Process DSC comments ---------------- */
  392.  
  393. private int
  394. pdf_dsc_process(gx_device_pdf * pdev, const gs_param_string_array * pma)
  395. {
  396.     /* This is just a place-holder. */
  397.     return 0;
  398. }
  399.